#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QToolButton>
#include<QPainter>
#include<QDebug>
#include<QVBoxLayout>
#include<QColorDialog>
#include<cmath>
#include<QCheckBox>
#include<QLineEdit>
#include<windows.h>
#include<QPushButton>
#include<QMouseEvent>
#include<QPalette>
using namespace std;


//两条直线交点的x坐标
int x_intersect(int x1, int y1, int x2, int y2,
                int x3, int y3, int x4, int y4)
{
    int num = (x1*y2 - y1*x2) * (x3-x4) -
              (x1-x2) * (x3*y4 - y3*x4);
    int den = (x1-x2) * (y3-y4) - (y1-y2) * (x3-x4);
    return num/den;
}

//返回交点的y坐标
int y_intersect(int x1, int y1, int x2, int y2,
                int x3, int y3, int x4, int y4)
{
    int num = (x1*y2 - y1*x2) * (y3-y4) -
              (y1-y2) * (x3*y4 - y3*x4);
    int den = (x1-x2) * (y3-y4) - (y1-y2) * (x3-x4);
    return num/den;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    type = LINE;

    //直线
    QToolButton* LINE_button = new QToolButton(this);
    LINE_button->setText("直线");
    connect(LINE_button,  &QToolButton::clicked, this, [=](){
        type = LINE;
        update();
    });
    ui->toolBar->addWidget(LINE_button);

    //多边形
    QToolButton* POLYGON_button = new QToolButton(this);
    POLYGON_button->setText("多边形");
    connect(POLYGON_button,  &QToolButton::clicked, this, [=](){
        type = POLYGON;
        update();
    });
    ui->toolBar->addWidget(POLYGON_button);

    //选择颜色
    QToolButton* color_button = new QToolButton(this);
    color_button->setStyleSheet("background-color: rgb(0, 0, 0)");
    connect(color_button, &QToolButton::clicked, this, [=](){
        QColorDialog dialog;
        QColor color = dialog.getColor(color, this, "选择字体颜色",
                                       QColorDialog::ShowAlphaChannel);
        if(this->now_color != color)
        {
            int r = 0, g = 0, b = 0;
            color.getRgb(&r,&g,&b);
            this->now_color.setRgb(r, g, b);
            color_button->setStyleSheet(QString("background-color: rgb(%1,%2,%3)").arg(r).arg(g).arg(b));
        }
    });
    ui->toolBar->addWidget(color_button);

    //裁剪
    QToolButton* CUT_button = new QToolButton(this);
    CUT_button->setText("裁剪");
    connect(CUT_button,  &QToolButton::clicked, this, [=](){
        cut();
        update();
    });
    ui->toolBar->addWidget(CUT_button);

    //清空按钮
    QToolButton* clear_button = new QToolButton(this);
    clear_button->setText("清空");
    connect(clear_button, &QToolButton::clicked, this, [=](){
        points.clear();
        lines.clear();
        cut_lines.clear();
        polygons.clear();
        cut_polygons.clear();
        temppoint.clear();
        update();
    });
    ui->toolBar->addWidget(clear_button);

    //裁剪框信息
    window[0] = QPoint(210,195);
    window[1] = QPoint(210,495);
    window[2] = QPoint(610,495);
    window[3] = QPoint(610,195);

}

MainWindow::~MainWindow()
{
    delete ui;
}

//鼠标事件
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
         add_line(event->pos());
    }
    else
    {
        add_line(QPoint(10,45));
    }

}

//画笔事件
void MainWindow::paintEvent(QPaintEvent *event)
{
    //设置画笔
    QPainter painter(this);
    QPen pen(QColor(0,0,0));
    QBrush brush(Qt::white);
    painter.setBrush(brush);
    painter.drawRect(QRect(10,45,800,600));
    painter.setPen(pen);
    painter.drawRect(QRect(210,195,400,300));//生成裁剪框
    if(type == LINE)//如果是裁剪直线的话
    {
        for(int i=0;i<lines.size();i++)//显示画的直线
        {
            QLine templine = lines[i].line;
            pen.setColor(lines[i].color);
            painter.setPen(pen);
            painter.drawLine(templine);
        }
        for(int i=0;i<cut_lines.size();i++)//显示裁剪之后的直线
        {
            QLine templine = cut_lines[i].line;
            pen.setColor(cut_lines[i].color);
            painter.setPen(pen);
            painter.drawLine(templine);
        }
    }
    else if(type == POLYGON)//如果是裁剪多边形
    {
        for(int i=0;i<polygons.size();i++)//显示未裁剪的多边形
        {
            QPolygon temppolygon = polygons[i].polygon;
            pen.setColor(polygons[i].color);
            painter.setBrush(Qt::NoBrush);
            painter.setPen(pen);
            painter.drawPolygon(temppolygon);
        }
        for(int i=0;i<cut_polygons.size();i++)//显示裁剪之后的多边形
        {
            QPolygon temppolygon = cut_polygons[i].polygon;
            pen.setColor(cut_polygons[i].color);
            pen.setWidth(3);
            painter.setBrush(Qt::NoBrush);
            painter.setPen(pen);
            painter.drawPolygon(temppolygon);
        }




    }

}

//添加点，起点终点
void MainWindow::add_line(QPoint point)
{
    if(point.x()>810||point.x()<10||point.y()<45||point.y()>645)//超出范围
    {
        qDebug() << "超出画图范围";
    }
    else
    {
        if(type == LINE)//裁剪直线
        {
            points.append(point);
            if(points.size()<2)
            {
                qDebug() << "请添加终点";
            }
            else
            {
                qDebug() << "成功添加直线";
                Line new_line;
                new_line.line = QLine(points[0],points[1]);
                new_line.color = now_color;
                lines.append(new_line);
                update();
                points.clear();
            }
        }
        else if(type == POLYGON)//裁剪多边形
        {
            if(point.x()==10&&point.y()==45)
            {
                Polygon new_polygon;
                for(int i=0;i<points.size();i++)
                {
                    new_polygon.polygon.append(points[i]);
                }
                new_polygon.color = now_color;
                polygons.append(new_polygon);
                update();
                points.clear();
            }
            else
            {
                points.append(point);
            }

        }

    }
}

//判断与裁剪框的四条边的关系
char MainWindow::encode(QPoint point)
{
    char ans = 0;
    if(point.x() < 210)
    {
        ans |= 0x1;
    }
    if(point.x() > 610)
    {
        ans |= 0x2;
    }
    if(point.y() > 495)
    {
        ans |= 0x4;
    }
    if(point.y() < 195)
    {
        ans |= 0x8;
    }
    return ans;
}

//裁剪直线
void MainWindow::cohen_cut(QPoint point1, QPoint point2,QColor color)//裁剪直线
{
    bool is_contain = false;//判断是否在裁剪框里
//    QRect bound = cut_polygon.boundingRect();
    while(true)
    {
        char code1 = encode(point1);
        char code2 = encode(point2);
        if(code1 == 0 && code2 == 0)//在里面
        {
            is_contain = true;
            Line new_line;
            new_line.line = QLine(point1,point2);
            new_line.color = color;
            cut_lines.append(new_line);
            break;
        }
        else if((code1 & code2) != 0)//在外面
        {
            is_contain = false;
            break;
        }
        else
        {
            double m = 0;
            if(point1.x() != point2.x())
            {
                m = (double)(point1.y() - point2.y()) / (double)(point1.x() - point2.x());
            }
            if(code1 == 0)//如果一个点在区域内，
            {
                swap(point1, point2);
                char temp = code1;
                code1 = code2;
                code2 = temp;
            }
            if(code1 & 0x1)//判断和左侧边的交点
            {
                point1.setY(point1.y() + m * (210 - point1.x()));
                point1.setX(210);
            }
            else
            {
                if(code1 & 0x2)//判断和右侧边的交点
                {
                    point1.setY(point1.y() + m * (610 - point1.x()));
                    point1.setX(610);
                }
                else
                {
                    if(code1 & 0x8)//判断和下侧边的交点
                    {
                        point1.setX(point1.x() + (195 - point1.y()) / m);
                        point1.setY(195);
                    }
                    else
                    {
                         if(code1 & 0x4)//判断和上侧边的交点
                         {
                             point1.setX(point1.x() + (495 - point1.y()) / m);
                             point1.setY(495);
                         }
                    }
                }
            }
        }
    }
}

//裁剪
void MainWindow::cut()
{
    if(type == LINE)//若果是裁剪直线的话
    {
        for(int i=0;i<lines.size();i++)//依次裁剪每一条直线
        {
            cohen_cut(lines[i].line.p1(),lines[i].line.p2(),lines[i].color);
        }
        lines.clear();
        update();
    }
    else if(type == POLYGON)//如果裁剪的是多边形
    {
        for(int i=0;i<polygons.size();i++)
        {
            suther_cut(polygons[i].polygon,polygons[i].color);
        }
    }
}

//交换两个点的坐标
void MainWindow::swap(QPoint &point1, QPoint &point2)
{
    int tx = point1.x();
    int ty = point1.y();
    point1.setX(point2.x());
    point1.setY(point2.y());
    point2.setX(tx);
    point2.setY(ty);
}

//裁剪多边形
void MainWindow::suther_cut(QPolygon polygon,QColor color)
{
//    qDebug() << polygon.size() << polygon[0];
    temppoint.clear();
    for(int j=0;j<4;j++)//对于上下左右4条边
    {
        for(int i=0;i<polygon.size();i++)
        {
            find_point(polygon[i],polygon[(i+1)%polygon.size()],j);//对于每条边找到应该加入几个点
        }
        polygon.clear();
        for(int i=0;i<temppoint.size();i++)
        {
            polygon.append(temppoint[i]);
        }
        temppoint.clear();
    }
    Polygon new_polygon;
    new_polygon.polygon = polygon;
    new_polygon.color = QColor(255,0,0);
    cut_polygons.append(new_polygon);
    for(int i=0;i<new_polygon.polygon.size();i++)
    {
        qDebug() << new_polygon.polygon[i];
    }


}

void MainWindow::find_point(QPoint point1, QPoint point2,int j)
{
    //计算point1，point2是否在区域内
    int sign1 = (window[(j+1)%4].x()-window[j].x())*(point1.y()-window[j].y())-
            (window[(j+1)%4].y()-window[j].y())*(point1.x()-window[j].x());
    int sign2 = (window[(j+1)%4].x()-window[j].x())*(point2.y()-window[j].y())-
            (window[(j+1)%4].y()-window[j].y())*(point2.x()-window[j].x());

    if(sign1<0&&sign2<0)//都在外面
    {
        temppoint.append(point2);
    }
    else if(sign1>=0&&sign2<0)//内外
    {
        int x = x_intersect(window[j].x(),window[j].y(),window[(j+1)%4].x(),window[(j+1)%4].y(),point1.x(),point1.y(),point2.x(),point2.y());
        int y = y_intersect(window[j].x(),window[j].y(),window[(j+1)%4].x(),window[(j+1)%4].y(),point1.x(),point1.y(),point2.x(),point2.y());

        temppoint.append(QPoint(x,y));
        temppoint.append(point2);
    }
    else if(sign1<0&&sign2>=0)//外内
    {
        int x = x_intersect(window[j].x(),window[j].y(),window[(j+1)%4].x(),window[(j+1)%4].y(),point1.x(),point1.y(),point2.x(),point2.y());
        int y = y_intersect(window[j].x(),window[j].y(),window[(j+1)%4].x(),window[(j+1)%4].y(),point1.x(),point1.y(),point2.x(),point2.y());

        temppoint.append(QPoint(x,y));
    }
}




